import java.io.*;

//TODO: config all of the path, parameters

public class JavaRuntime {

	// running program use this name
	private static String programName = "myMain";
	private static String btracePath = "/home/L/workspace/eclipse/SHK/CoolSW/myTest/bin/bTraceScript/BTraceScript.class";
	private static String stapPath = "/home/L/workspace/eclipse/SHK/CoolSW/myTest/systemTap/cpu_profiler_sampling.stp";
	private static String jsonPath = "/home/L/workspace/eclipse/SHK/CoolSW/myTest/json/test.json";
	private static String eureqaServer = "/home/L/Program/eureqa/eureqa_api_1_04_0/server/linux/eureqa_server_0_84_0/eureqa_server";
	private static String eureqaClient = "/home/L/workspace/eclipse/SHK/CoolSW/myTest/eureqa/eureqaSort";

	/**
	 * get the thread number.
	 */
	public static String getThreadNr() {

		String threadNr = "-1";
		try {
			ProcessBuilder pb = new ProcessBuilder("jps");
			Process process = pb.start();
			BufferedReader myBuffer = new BufferedReader(new InputStreamReader(
					process.getInputStream()));
			String l = null;
			while ((l = myBuffer.readLine()) != null) {
				if (l.endsWith(programName)) {
					threadNr = l.substring(0, l.length() - 7);
					System.out
							.println("the thread number of java function is: "
									+ threadNr);
					break;
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return threadNr;
	}

	/**
	 * run the Btrace with the thread number.
	 * 
	 * @param threadNr
	 *            running thread number.
	 */
	public static void runBtrace(String threadNr) {

		try {
			ProcessBuilder pb = new ProcessBuilder("btrace", threadNr,
					btracePath);
			System.out.println("Btrace running!");
			Process process = pb.start();
			// printError(process);
			// printInput(process);
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * run the stap with the thread number.
	 * 
	 * @param threadNr
	 * @return stap process
	 */
	public static String runStap(String threadNr) {
		Process process = null;
		String stapThrNr = "-1";
		try {
			ProcessBuilder pb = new ProcessBuilder("stap", stapPath, "-F",
					"-o", jsonPath, "-x", threadNr, "-v");
			// ProcessBuilder pb = new ProcessBuilder("stap", stapPath,"-x",
			// threadNr, "-v");
			System.out.println("systemTap running!");
			process = pb.start();
			// printError(process);
			stapThrNr = printInput(process);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return stapThrNr;
	}

	/**
	 * kill the systemTap process.
	 * 
	 * @param stapThrNr
	 *            process number of systemTap.
	 */
	public static void killStap(String stapThrNr) {
		ProcessBuilder pb = new ProcessBuilder("kill", "-s", "SIGTERM",
				stapThrNr);
		try {
			pb.start();
			System.out.println("systemTap is killed!");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * wait till finish analyzing json file.
	 * 
	 * @throws IOException
	 */
	public static void analyzeJson() {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out
				.println("please analyze the .json file and hit ENTER when ready...");
		try {
			br.read();
			System.out.println("finish analyzing .json file!");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * run the eureqa Server.
	 */
	public static void runEureqaServer() {
		try {
			new ProcessBuilder(eureqaServer).start();
			System.out.println("eureqaServer running!");
		} catch (Exception e) {
			System.out.println("Error exec!");
		}
	}

	/**
	 * kill the eureqa server process.
	 */
	public static void killEureqaServer(){
		try {
			new ProcessBuilder("pkill","eureqa_server").start();
			System.out.println("eureqaServer is killed!");
		} catch (Exception e) {
			System.out.println("Error exec!");
		}
	}
	/**
	 * run the eureqa Client.
	 */
	public static void runEureqaClinet() {
		try {
			Process cleintProcess = new ProcessBuilder(eureqaClient).start();
			printInput(cleintProcess);
			System.out.println("eureqaClient running!");
		} catch (Exception e) {
			System.out.println("Error exec!");
		}
	}

	/**
	 * wait n seconds.
	 * 
	 * @param sec second
	 */
	public static void wait(int sec) {
		try {
			Thread.sleep(sec*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	/**
	 * print error.
	 * 
	 * @param process
	 *            process for btrace/stap/eureqa
	 */
	public static void printError(Process process) {
		BufferedReader myBuffer = new BufferedReader(new InputStreamReader(
				process.getErrorStream()));
		String l = null;
		try {
			while ((l = myBuffer.readLine()) != null) {
				System.out.println(l);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * print input message.
	 * 
	 * @param process
	 *            process for btrace/stap/eureqa
	 * 
	 * @return the last line of print
	 */
	public static String printInput(Process process) {
		BufferedReader myBuffer = new BufferedReader(new InputStreamReader(
				process.getInputStream()));
		String lastline="";
		String l = null;
		try {
			while ((l = myBuffer.readLine()) != null) {
				System.out.println(l);
				lastline=l;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return lastline;
	}

	public static void main(String args[]) {

		String threadNr = getThreadNr();
		String stapThrNr="-1";
		if (threadNr.equals("-1")) {
			System.out.println("our program not running!");
		} else {
			runBtrace(threadNr);
			wait(2);
			stapThrNr = runStap(threadNr);
			wait(2);
			// after we should kill systemTap.
//			 killStap(stapThrNr);
		}
		
		// even our program not running, it can still analyze the existing .json
		// file and exported file
		analyzeJson();
		wait(2);
		runEureqaServer();
		wait(2);
		runEureqaClinet();
		// kill the process eureqa server:
		 killEureqaServer();
	}

}